#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
请求构建器

该模块提供了构建HTTP请求的工具类，支持链式调用，简化请求构建过程。

创建时间: 2023-07-15
作者: Python Tools Team
"""

from typing import Dict, Any, Optional, Union, List, Tuple, Callable, Type, TypeVar
import json
from urllib.parse import urlencode

from .http_client import HttpClient, HttpResponse, HttpMethod


class RequestBuilder:
    """
    请求构建器类
    
    提供了链式调用API，用于构建和发送HTTP请求。
    """
    
    def __init__(self, client: HttpClient):
        """
        初始化请求构建器
        
        Args:
            client: HTTP客户端实例
        """
        self._client = client
        self._method = HttpMethod.GET
        self._url = ""
        self._params = {}
        self._headers = {}
        self._cookies = {}
        self._data = None
        self._json_data = None
        self._timeout = None
        self._verify = None
        self._cert = None
        self._proxies = None
        self._auth = None
        self._allow_redirects = True
        self._stream = False
    
    def method(self, method: Union[str, HttpMethod]) -> 'RequestBuilder':
        """
        设置HTTP方法
        
        Args:
            method: HTTP方法
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._method = method
        return self
    
    def url(self, url: str) -> 'RequestBuilder':
        """
        设置请求URL
        
        Args:
            url: 请求URL
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._url = url
        return self
    
    def param(self, key: str, value: Any) -> 'RequestBuilder':
        """
        添加单个URL参数
        
        Args:
            key: 参数名
            value: 参数值
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._params[key] = value
        return self
    
    def params(self, params: Dict[str, Any]) -> 'RequestBuilder':
        """
        设置URL参数字典
        
        Args:
            params: 参数字典
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._params.update(params)
        return self
    
    def header(self, key: str, value: str) -> 'RequestBuilder':
        """
        添加单个请求头
        
        Args:
            key: 请求头名
            value: 请求头值
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._headers[key] = value
        return self
    
    def headers(self, headers: Dict[str, str]) -> 'RequestBuilder':
        """
        设置请求头字典
        
        Args:
            headers: 请求头字典
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._headers.update(headers)
        return self
    
    def cookie(self, key: str, value: str) -> 'RequestBuilder':
        """
        添加单个cookie
        
        Args:
            key: cookie名
            value: cookie值
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._cookies[key] = value
        return self
    
    def cookies(self, cookies: Dict[str, str]) -> 'RequestBuilder':
        """
        设置cookies字典
        
        Args:
            cookies: cookies字典
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._cookies.update(cookies)
        return self
    
    def data(self, data: Any) -> 'RequestBuilder':
        """
        设置请求体数据
        
        Args:
            data: 请求体数据
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._data = data
        self._json_data = None  # 清除JSON数据，避免冲突
        return self
    
    def form_data(self, form_data: Dict[str, Any]) -> 'RequestBuilder':
        """
        设置表单数据
        
        Args:
            form_data: 表单数据字典
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._data = form_data
        self._json_data = None  # 清除JSON数据，避免冲突
        self.header('Content-Type', 'application/x-www-form-urlencoded')
        return self
    
    def json(self, json_data: Dict[str, Any]) -> 'RequestBuilder':
        """
        设置JSON请求体数据
        
        Args:
            json_data: JSON数据字典
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._json_data = json_data
        self._data = None  # 清除普通数据，避免冲突
        self.header('Content-Type', 'application/json')
        return self
    
    def timeout(self, timeout: Union[float, Tuple[float, float]]) -> 'RequestBuilder':
        """
        设置请求超时时间
        
        Args:
            timeout: 超时时间，可以是单个浮点数或(连接超时, 读取超时)的元组
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._timeout = timeout
        return self
    
    def verify(self, verify: bool) -> 'RequestBuilder':
        """
        设置是否验证SSL证书
        
        Args:
            verify: 是否验证SSL证书
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._verify = verify
        return self
    
    def cert(self, cert: Union[str, Tuple[str, str]]) -> 'RequestBuilder':
        """
        设置SSL客户端证书
        
        Args:
            cert: SSL客户端证书，可以是包含证书和密钥的元组
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._cert = cert
        return self
    
    def proxy(self, protocol: str, proxy_url: str) -> 'RequestBuilder':
        """
        添加单个代理配置
        
        Args:
            protocol: 协议（http或https）
            proxy_url: 代理URL
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        if self._proxies is None:
            self._proxies = {}
        self._proxies[protocol] = proxy_url
        return self
    
    def proxies(self, proxies: Dict[str, str]) -> 'RequestBuilder':
        """
        设置代理配置字典
        
        Args:
            proxies: 代理配置字典
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._proxies = proxies
        return self
    
    def auth(self, auth: Any) -> 'RequestBuilder':
        """
        设置认证处理器
        
        Args:
            auth: 认证处理器
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._auth = auth
        return self
    
    def allow_redirects(self, allow: bool) -> 'RequestBuilder':
        """
        设置是否允许重定向
        
        Args:
            allow: 是否允许重定向
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._allow_redirects = allow
        return self
    
    def stream(self, stream: bool) -> 'RequestBuilder':
        """
        设置是否使用流式传输
        
        Args:
            stream: 是否使用流式传输
            
        Returns:
            RequestBuilder: 当前构建器实例（用于链式调用）
        """
        self._stream = stream
        return self
    
    def build(self) -> Dict[str, Any]:
        """
        构建请求参数字典
        
        Returns:
            Dict[str, Any]: 请求参数字典
        """
        request_kwargs = {
            'method': self._method,
            'url': self._url,
            'params': self._params or None,
            'headers': self._headers or None,
            'cookies': self._cookies or None,
            'timeout': self._timeout,
            'verify': self._verify,
            'cert': self._cert,
            'proxies': self._proxies,
            'auth': self._auth,
            'allow_redirects': self._allow_redirects,
            'stream': self._stream
        }
        
        if self._json_data is not None:
            request_kwargs['json_data'] = self._json_data
        elif self._data is not None:
            request_kwargs['data'] = self._data
        
        return request_kwargs
    
    def execute(self) -> HttpResponse:
        """
        执行请求
        
        Returns:
            HttpResponse: HTTP响应对象
        """
        return self._client.request(
            method=self._method,
            url=self._url,
            params=self._params or None,
            data=self._data,
            json_data=self._json_data,
            headers=self._headers or None,
            cookies=self._cookies or None,
            timeout=self._timeout,
            verify=self._verify,
            cert=self._cert,
            proxies=self._proxies,
            auth=self._auth,
            allow_redirects=self._allow_redirects,
            stream=self._stream
        )
    
    def get(self, url: Optional[str] = None) -> HttpResponse:
        """
        执行GET请求
        
        Args:
            url: 请求URL，如果提供则覆盖之前设置的URL
            
        Returns:
            HttpResponse: HTTP响应对象
        """
        if url:
            self.url(url)
        self.method(HttpMethod.GET)
        return self.execute()
    
    def post(self, url: Optional[str] = None) -> HttpResponse:
        """
        执行POST请求
        
        Args:
            url: 请求URL，如果提供则覆盖之前设置的URL
            
        Returns:
            HttpResponse: HTTP响应对象
        """
        if url:
            self.url(url)
        self.method(HttpMethod.POST)
        return self.execute()
    
    def put(self, url: Optional[str] = None) -> HttpResponse:
        """
        执行PUT请求
        
        Args:
            url: 请求URL，如果提供则覆盖之前设置的URL
            
        Returns:
            HttpResponse: HTTP响应对象
        """
        if url:
            self.url(url)
        self.method(HttpMethod.PUT)
        return self.execute()
    
    def delete(self, url: Optional[str] = None) -> HttpResponse:
        """
        执行DELETE请求
        
        Args:
            url: 请求URL，如果提供则覆盖之前设置的URL
            
        Returns:
            HttpResponse: HTTP响应对象
        """
        if url:
            self.url(url)
        self.method(HttpMethod.DELETE)
        return self.execute()
    
    def patch(self, url: Optional[str] = None) -> HttpResponse:
        """
        执行PATCH请求
        
        Args:
            url: 请求URL，如果提供则覆盖之前设置的URL
            
        Returns:
            HttpResponse: HTTP响应对象
        """
        if url:
            self.url(url)
        self.method(HttpMethod.PATCH)
        return self.execute()